/**
 * @Name: common-api
 * @Author: tyq
 * @version: 1.0.2
 * @Deprecated: 通用工具包-api
 * ----------------------------------------------------------------------------------------------------------------------------------
 * StorageEnum        枚举: 缓存枚举, LocalStorage & SessionStorage
 * getUuid            生成UUID 
 * isEmpty            校验对象是否为空对象: null, undefined, NaN
 * isEmptyObj         校验对象是否为空对象: {}, [], "", null, undefined
 * isNumber           校验对象是否为数字
 * toNumber           格式转换：数字格式(String => Number)
 * dateFormat         格式转换：时间格式
 * moneyFormat        格式转换：金额“,”分段格式化
 * addNumberSpace     格式转换：数字补位, 补位字符 0
 * arrayToTree        格式转换：数组转树
 * hasClass           DOM元素: 判断DOM元素是否包含此类名选择器
 * addClass           DOM元素: 向DOM元素添加类选择器
 * removeClass        DOM元素: 删除DOM元素的类选择器
 * setStorage         Storage: 设置 Storage 缓存
 * getStorage         Storage: 获取 Storage 缓存
 * validStorage       Storage: 校验 Storage 缓存是否存在
 * removeStorage      Storage: 根据 key 删除 Storage 缓存
 * clearStorage       Storage: 清理 Storage 缓存
 * isFullScreen       浏览器全屏: 判断浏览器是否是全屏状态
 * setFullScreen      浏览器全屏: 设置浏览器全屏
 * exitFullScreen     浏览器全屏: 浏览器退出全屏
 * toggleFullScreen   浏览器全屏: 浏览器全屏切换
 */


/****** StorageEnum 缓存枚举, LocalStorage & SessionStorage **************************************************************************/
export const StorageEnum = {
  LocalStorage: 'local',
  SessionStorage: 'session'
}


/****** getUuid 生成UUID ************************************************************************************************************/
/**
 * 获取uuid
 * @returns {string} uuid
 */
 export function getUuid() {
  return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  })
}


/****** isEmpty 校验对象是为空对象 ****************************************************************************************************/
/**
 * 校验对象是为空对象: null, undefined, NaN
 * @param {Object} value 校验对象, 默认为 null
 * @param {Boolean} clearSpace 是否去掉不可见字符: value 为 string 类型时有效, 默认为 false
 * @returns true-空对象, false-非空对象
 */
export function isEmpty(value = null, clearSpace = false) {
  if (value == null || void 0 == value) return true
  // 对象的类型
  const _type = typeof value;

  if (_type === 'string') {
    // 清理空格、制表符后再校验
    if (clearSpace) {
      return value.replace(/\s+/g, '').length == 0
    } else {
      return value.length == 0
    }
  }

  // 校验数字类型的是否为NaN
  if (_type === 'number') return isNaN(value)
  return false
}


/****** isEmptyObj 校验对象是为空对象 *************************************************************************************************/
/**
 * 校验对象是为空对象: {} [] 字符串类型
 * @param obj
 * @returns {boolean}
 */
export function isEmptyObj (obj) {
  if(obj == null || obj == void 0) return true
  return Object.keys(obj).length == 0;
}


/****** isNumber 校验对象是为数字 *****************************************************************************************************/
/**
 * 校验对象是为数字
 * @param obj
 * @returns {boolean}
 */
 export function isNumber (obj) {
  if(typeof obj === 'string' || typeof obj === 'number'){
    return !isNaN(obj/1);
  }
  return false;
}


/****** toNumber 格式转换：数字格式(String => Number) *********************************************************************************/
/**
 * 数字格式转化：String => Number
 * @param {String} str 
 * @returns {Number} Number格式，如果参数不可转，返回0
 */
export function toNumber(str){
  return isNumber(str) ? str/1 : 0;
}


/****** dateFormat 格式转换：时间格式 *************************************************************************************************/
/**
 * 时间格式转换
 * @param { String | Date } val 需要转换的值
 * @param { String } format 转换的格式，默认年月日(YYYY-MM-DD)
 * @returns 格式化日期字符串
 */
export function dateFormat(val = null, format = "YYYY-MM-DD") {

  if (isEmpty(val) || isEmpty(format)) return val;
  if (typeof format !== 'string') return val;
  if (typeof val === 'string') val = val.replace('T', ' ');

  try {
    let date = new Date(val);
    const fullYear = date.getFullYear(),
    month = date.getMonth() + 1,
    dateday = date.getDate(),
    hours = date.getHours(),
    minutes = date.getMinutes(),
    seconds = date.getSeconds()

    const fm = {
      YYYY: fullYear,
      yyyy: fullYear,
      YYY: fullYear,
      yyy: fullYear,
      YY: addNumberSpace(fullYear % 100),
      yy: addNumberSpace(fullYear % 100),
      Y: fullYear % 100,
      y: fullYear % 100,
      MM: addNumberSpace(month),
      M: month,
      DD: addNumberSpace(dateday),
      dd: addNumberSpace(dateday),
      D: date.getDate(),
      d: date.getDate(),
      HH: addNumberSpace(hours),
      hh: addNumberSpace(hours),
      H: hours,
      h: hours,
      mm: addNumberSpace(minutes),
      m: minutes,
      ss: addNumberSpace(seconds),
      s: seconds
    }

    let res = format;
    for (let key in fm) {
      res = res.replace(new RegExp(key, 'g'), fm[key]);
    }

    return res;
  } catch (e) {
    console.log(e)
    return val;
  }
}


/****** moneyFormat 格式转换：金额“,”分段格式化 ****************************************************************************************/
/**
 * 金额分段格式化
 * @param {number} money 
 * @param {bit} bit 
 */
 export function moneyFormat(money = 0, bit = 3){
  if (bit == null || bit == null) return money;
  if (isEmpty(money) || isEmpty(bit)) return null;
  const numType = typeof money;
  const powType = typeof bit;

  if (numType === 'number' && money < 0) return money;
  if (powType === 'number' && bit < 0) return money;
  if (numType === 'string' && isEmpty(money / 1)) return money;
  if (powType === 'string' && isEmpty(bit / 1)) return money;

  bit = bit/1;
  bit = bit > 1 ? bit - 1 : bit < 1 ? 1 : bit;
  const mp = Math.pow(10, bit);
  money = money.toString();

  // 有小数点
	if(money.indexOf('.') != -1){
		let _mon = money.split('.')[0];
		if(_mon.length <= mp.toString().length){
			return money;
		}
		
		let m = _mon.length % mp.toString().length;
		let str = _mon.slice(0, m);
		for(let i = m - 1; i < _mon.length-1; i += mp.toString().length){
			str += ',' + _mon.slice(i, i + mp.toString().length);
		}
		
		return str;
	}else{
		let m = money.length % mp.toString().length;
		let str = money.slice(0, m);
		for(let i = m; i < money.length-1; i += mp.toString().length){
			str += ',' + money.slice(i, i + mp.toString().length);
		}
		
		return str;
	}
}


/****** addNumberSpace 格式转换：数字补位, 补位字符 0 **********************************************************************************/
/**
 * 数字补位, 补位字符 0
 * @param {Number|String} num 数字
 * @param {Number|String} pow 需补位量, 用作10的n次幂(方)
 * @returns 补位结果
 */
export function addNumberSpace(num = 0, pow = 1) {
  if (num == null || pow == null) return num;
  if (isEmpty(num) || isEmpty(pow)) return null;
  const numType = typeof num;
  const powType = typeof pow;

  if (numType === 'number' && num < 0) return num;
  if (powType === 'number' && pow < 0) return num;
  if (numType === 'string' && isEmpty(num / 1)) return num;
  if (powType === 'string' && isEmpty(pow / 1)) return num;

  const mp = Math.pow(10, pow / 1);
  if (num / 1 < mp) {
    let _num = num.toString();
    for (let i = 0; i < mp.toString().length - _num.toString().length; i++) {
      _num = '0' + _num;
    }

    return _num;
  }
  return num;
}


/****** arrayToTree 格式转换：数组转树 ************************************************************************************************/
/**
 * 数组转树
 * @param {Array|String} array 需要转化的数组
 * @param {String} key 关键字字段名
 * @param {String} parentKey 父级编号字段
 * @param {String} childrenKey 孩子节点字段
 * @returns {Array} 树
 */
export function arrayToTree(array = [], key = 'id', parentKey = 'parentId', childrenKey = 'children') {
  if (isEmpty(array)) return []
  // 默认参数
  let _default = {
    data: [],
    resourceData: [],
    key: "id",
    parentKey: 'parentId',
    childrenKey: 'children'
  }

  // 如果是字符串，先转换为对象再校验格式
  if (typeof array === 'string') {
    try {
      let _arr = JSON.parse(array);
      if (_arr instanceof Array) {
        // 反序列化后如果是数组，则继续
        _default.resourceData = _arr;
      } else {
        // 不是数组，则格式错误
        console.log('数据格式错误', _arr);
        return _default.data;
      }
    } catch (e) {
      // 反序列化失败, 说明数据格式有误
      console.log('数据格式错误', e);
      return _default.data;
    }
  } else if (array instanceof Array) {
    // 如果是数组，直接克隆
    _default.resourceData = JSON.parse(JSON.stringify(array));
  } else {
    // 其他数据格式，不满足要求
    console.log('数据格式错误', _arr);
    return _default.data;
  }

  if (!isEmpty(key)) _default.key = key;
  if (!isEmpty(parentKey)) _default.parentKey = parentKey;
  if (!isEmpty(childrenKey)) _default.childrenKey = childrenKey;
  if (_default.resourceData.length) {
    let allIdMap = {};

    _default.resourceData.forEach(item => {
      const _id = item[_default.key];
      if (!isEmpty(_id)) allIdMap[_id] = item;
    })

    _default.resourceData.forEach(item => {
      const _pid = item[_default.parentKey];
      if (!isEmpty(_pid)) {
        const parent = allIdMap[_pid];
        if (parent) {
          // 如果存在父级节点，将当前节点添加到父级节点的孩子节点集合
          if (isEmpty(parent[_default.childrenKey])) parent[_default.childrenKey] = [];
          parent[_default.childrenKey].push(item);
        } else {
          // 顶级节点，这里的item是引用对象
          _default.data.push(item);
        }
      }
    })
  }

  return _default.data;
}


/****** hasClass 判断DOM元素是否包含此类名 ********************************************************************************************/
/**
 * 判断DOM元素是否包含此类名
 * @param {HTMLElement} el dom元素
 * @param {String} className 类名
 * @returns true-包含, false-不包含
 */
export function hasClass(el, className) {
  if (isEmpty(el) || isEmpty(className, true)) return false
  if (typeof className !== 'string') return false
  if (isEmpty(el.classList)) return false
  return el.classList.contains(className)
}


/****** addClass 向DOM元素添加类名 ****************************************************************************************************/
/**
 * 向DOM元素添加类名
 * @param {HTMLElement} el dom元素
 * @param {String} className 类名
 */
export function addClass(el, className) {
  if (isEmpty(el) || isEmpty(className, true)) return
  if (typeof className !== 'string') return
  if (isEmpty(el.classList)) return
  el.classList.add(className)
}


/****** removeClass 删除DOM元素的类名 ****************************************************************************************************/
/**
 * 删除DOM元素的类名
 * @param {HTMLElement} el dom元素
 * @param {String} className 类名
 */
export function removeClass(el, className) {
  if (isEmpty(el) || isEmpty(className, true)) return
  if (typeof className !== 'string') return
  if (isEmpty(el.classList)) return
  el.classList.remove(className)
}


/****** setStorage 设置 Storage 缓存 **************************************************************************************************/
/**
 * 设置 Storage 缓存
 * @param {String} key 关键字
 * @param {String} value 值
 * @param {String} type 类型: local-localStorage, session-sessionStorage, 默认为 local
 */
export function setStorage(key = null, value = null, type = StorageEnum.LocalStorage) {
  if (isEmpty(key)) return
  if (typeof key !== 'string') return

  const obj = JSON.stringify({
    dataType: typeof (value),
    content: value
  })

  if (type == StorageEnum.LocalStorage) {
    localStorage.setItem(key, obj);
  } else if (type == StorageEnum.SessionStorage) {
    sessionStorage.setItem(key, obj);
  }
}


/****** getStorage 获取 Storage 缓存 **************************************************************************************************/
/**
 * 
 * @param {String} key 
 * @param {String} type 
 */
export function getStorage(key = null, type = StorageEnum.LocalStorage) {
  if (isEmpty(key)) return
  if (typeof key !== 'string') return

  let _storage;
  if (type == StorageEnum.LocalStorage) {
    _storage = localStorage.getItem(key);
  } else if (type == StorageEnum.SessionStorage) {
    _storage = sessionStorage.getItem(key);
  }

  if (!isEmpty(_storage)) {
    _storage = JSON.parse(_storage);

    switch (_storage.dataType) {
      case 'number': _storage = _storage.content / 1; break;
      case 'string':
      case 'boolean':
      case 'object': _storage = _storage.content; break;
      default: _storage = _storage.content;
    }
  }

  return isEmpty(_storage) ? '' : _storage
}


/****** validStorage 校验 Storage 缓存是否存在 ****************************************************************************************/
/**
 * 校验 Storage 缓存是否存在
 * @param {String} key 关键字
 * @param {String} type 类型: local-localStorage, session-sessionStorage, 默认为 local
 * @returns true-存在, false-不存在
 */
export function validStorage(key = null, type = StorageEnum.LocalStorage) {
  if (isEmpty(key, true)) return false
  if (typeof key != 'string') return false

  const value = type == StorageEnum.LocalStorage ? localStorage.getItem(key) : type == StorageEnum.SessionStorage ? sessionStorage.getItem(key) : ''
  return !isEmpty(value)
}


/****** removeStorage 根据 key 删除 Storage 缓存 *************************************************************************************/
/**
 * 根据 key 删除 Storage 缓存
 * @param {String} key 关键字
 * @param {String} type 类型: local-localStorage, session-sessionStorage, 默认为 local
 */
export function removeStorage(key = null, type = StorageEnum.LocalStorage) {
  if (isEmpty(key)) return
  if (typeof key !== 'string') return

  if (type == StorageEnum.LocalStorage) {
    localStorage.removeItem(key);
  } else if (type == StorageEnum.SessionStorage) {
    sessionStorage.removeItem(key);
  }

}


/****** clearStorage 清理 Storage 缓存 ***********************************************************************************************/
/**
 * 清理 Storage 缓存
 */
export function clearStorage() {
  localStorage.clear()
  sessionStorage.clear()
}


/****** isFullScreen 判断浏览器是否是全屏状态 *****************************************************************************************/
/**
 * 判断浏览器是否是全屏状态
 * @returns true-全屏, false-非全屏
 */
export function isFullScreen() {
  return document.isFullScreen ||
    document.mozIsFullScreen ||
    document.webkitIsFullScreen;
}


/****** setFullScreen 设置浏览器全屏 *************************************************************************************************/
/**
* 设置浏览器全屏
*/
export function setFullScreen() {
  if (document.documentElement.requestFullScreen) {
    document.documentElement.requestFullScreen();
  } else if (document.documentElement.webkitRequestFullScreen) {
    document.documentElement.webkitRequestFullScreen();
  } else if (document.documentElement.mozRequestFullScreen) {
    document.documentElement.mozRequestFullScreen();
  }
}


/****** exitFullScreen 浏览器退出全屏 ************************************************************************************************/
/**
 * 浏览器退出全屏
 */
export function exitFullScreen() {
  if (document.documentElement.requestFullScreen) {
    document.exitFullScreen();
  } else if (document.documentElement.webkitRequestFullScreen) {
    document.webkitCancelFullScreen();
  } else if (document.documentElement.mozRequestFullScreen) {
    document.mozCancelFullScreen();
  }
}


/****** toggleFullScreen 浏览器全屏切换 **********************************************************************************************/
/**
 * 浏览器全屏切换
 */
export function toggleFullScreen() {
  isFullScreen() ? exitFullScreen() : setFullScreen();
}